#define _POSIX_C_SOURCE 1
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
/*#include "fonction_serveur.h"*/
#include "sauvegarde.h"

#define TBUFF 50

#define NI_MAXHOST 1023
#define NI_MAXSERV 32

/*#define true  1 
#define false 0*/

typedef int SOCKET;


int main(int argc, char* argv[])
{
	/*Récupération du port d'écoute depuis la console*/
	char * port ;
	if ( argc != 2 )
	{
		fprintf(stderr, "usage : %s <num port >\n" , argv[0]) ;
		exit(1) ;
	}

	port = argv[1];
	/*Fin de la récupération du port d'écoute depuis le serveur*/

	/*Initialisation des variables pour l'ouverture du serveur*/
	SOCKET s = -1;
	struct addrinfo hints; /*structure d'initalisation de la demande de port*/
	struct addrinfo *result, *rp; /*resultat et pseudo itérateur*/
	int bon, res; /*Variables booléennes de test*/
	char hname[NI_MAXHOST], sname[NI_MAXSERV]; /*hostname du serveur et hostname du client*/
	struct sockaddr_storage clientInfo; /*Structure de stockage des informations client*/
	socklen_t recsize = sizeof(clientInfo); /*Utilisé pour l'acceptation*/

	/*Initialisation à 0 de la variable hints*/
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_PASSIVE;
	hints.ai_protocol = 0;

	/*Demande envoyée pour le port demandé*/
	res = getaddrinfo(NULL, port, &hints, &result);
	if( res != 0 ) { /*Gestion d'erreur sur la demande de port*/
		fprintf(stderr, "problem : getaddrinfo => %s\n", gai_strerror(res));
		exit(1);
	}

	/*Si res = 0; result a donc été remplie par la fonction getaddrinfo et contient donc une liste des addresses correspondant à la demande faite. On va donc itérer dessus jusqu'à ce que l'on puisse établir une connection*/

	/*rp est utilisé ici comme pseudo-itérateur*/
	rp = result;
	bon = 0;
	/*Itération en cours ...*/
	while(rp != NULL) {

		int yes = 1;

		/*On tente de créer la socket, s sera le descripteur de la socket*/
		s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if( s==-1 ) {
			perror("creation de la socket !");
			continue;
		}

		/*Partie récupérée du cours : évite les rejets du système si le précédent test a planté*/
		res = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
		if(res == -1) {
			perror ("setsockopt") ;
			continue ;
		}
		/*Fin de la partie récupérée du cours*/

		/*On tente maintenant de binder l'adresse*/
		res = bind(s, rp->ai_addr, rp->ai_addrlen);
		if( res == 0 ) {
			bon = 1;
			printf("Connection de la socket %d sur le port %s\n", s, port);
			break;
		} else {
			perror("Probleme de bind sur la socket");
			close(s);	
		}

		rp = rp->ai_next;
	}
	/*Fin de l'itération*/

	if( bon == 0) {
		fprintf(stderr, "Le bind s'est mal ou non effectué\n");
		exit(1);
	}

	freeaddrinfo(result);
	/*printf("Le serveur %s est en attente de connexions sur %s ...\n", hname, sname);*/
	res = listen(s, 10);

	if(res < 0) {
		perror("L'écoute a échoué \n");
	}

	int t;
	do{
	t = accept(s, (struct sockaddr *)&clientInfo, &recsize);
	res = getnameinfo((struct sockaddr*) &clientInfo, recsize, hname, NI_MAXHOST, sname, NI_MAXSERV, NI_NUMERICSERV);

	if(res != 0) {
		fprintf(stderr, "problem : getnameinfo => %s\n", gai_strerror(res));
	}
	printf("Le serveur a un client %s sur le port %s\n", hname, sname);
	
	/*En Attente de pourvoir quitter */
	char p[TBUFF];
	char nomemp[TBUFF];
	char c[TBUFF];
	
	
	
	
		/* demande du nom de l'employé */
			if(recv(t, p, sizeof(p), 0)>0)
			{
				strcpy(nomemp , p );
				printf(" le nom de l'employé : %s \n", nomemp);
			}
			else perror("nom de l'employé \n");
		
		do
		{
			/*recuperation de la demande du client*/ 
			if(recv(t, c, sizeof(c), 0)>0) 
			{
				printf("%s\n",c);

				if (strcmp(c ,"1") == 0)
				{
					printf("Vous souhaitez effectuer l'action %s, en attente de la reception du fichier\n", c);
					strcpy(p , "OK");
					send(t,p,sizeof(p),0);
					if(recv(t, p, sizeof(p), 0)>0)
					{
						printf("rapport reçu \n");
						if(Ecrit(p, nomemp) == 0)
						{
							printf("sauvegarde réussi \n");
							strcpy(p , "ok");
							send(t,p,sizeof(p),0);
						}
						else
						{
							perror("erreur sauvegarde rapport\n");
						}
					}
					else perror("envoi du rapport\n");
			
				}
				else if (strcmp(c,"2") == 0)
				{
					printf("Vous souhaitez effectuer l'action %s, en attente de l'envoi du fichier\n", c);
					if (OuvreRapport(nomemp)!=-1)
					{
						printf("ouverture réussie");
						strcpy (p , "ok");
						send(t,p,sizeof(p),0);
					}
					else
					{
					perror ("ouverture fail");
					}		
				}
				else if (strcmp(c,"4") == 0){
				printf ("fermeture du serveur");
					close(s);
			}
			}

		}while (strcmp(c ,"3") != 0) ;
		
	}while(1);

	return 0;
}
